package com.wenshi.system.service.impl;


import com.wenshi.common.constant.ModbusConstants;
import com.wenshi.common.core.domain.ModbusFrame;
import com.wenshi.common.utils.ByteUtils;
import com.wenshi.common.utils.ChannelMap;
import com.wenshi.system.domain.vo.request.ModbusRequest;
import com.wenshi.system.service.GetDeviceStatusService;
import com.wenshi.system.service.ModbusMappingService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static com.wenshi.system.init.InitMappingMap.*;


@Service
@Slf4j
public class GetDeviceStatusServiceImpl implements GetDeviceStatusService {

    // 初始化transactionId为0
    private static int currentTransactionId = 65533;

    @Autowired
    private ModbusMappingService modbusMappingService;

    @Override
    public void getDeviceStatus(String deviceIp) {
        //plc地址和内容的映射
//        Map<String,String> plcAndDescMap = new HashMap<>();
//        Map<Integer,String> modbusAndResultMap = new HashMap<>();
//        Map<Integer,String> modbusAndPlcMap = new HashMap<>();
//        Map<String,String> resultAndDescMap = new HashMap<>();
//        List<ModbusMapping> mappingList = modbusMappingService.list();
//        for (ModbusMapping modbusMapping : mappingList) {
//            String plcAddress = modbusMapping.getPlcAddress();
//            String functionDesc = modbusMapping.getFunctionDesc();
//            Integer modbusAddress = modbusMapping.getModbusAddress();
//
//            plcAndDescMap.put(plcAddress,functionDesc);
//            modbusAndPlcMap.put(modbusAddress, plcAddress);
//        }
        //构建读取连续的线圈请求
//        int startAddress = 5; // 起始地址
//        int size = 4;
//        byte code = ModbusConstants.READ_HOLDING_REGISTERS;
//
//        ModbusFrame modbusRequest = createModbusRequest(startAddress, size, code);
//        Channel channel = ChannelMap.getChannel(deviceId);
//        channel.writeAndFlush(modbusRequest);
        getDeviceStatusList(deviceIp);

    }

    /**
     * 获取设备运行页面状态数据
     *
     * @param deviceIp
     */
    @Override
    public boolean getRunPageStatus(String deviceIp) {
        // 定义Modbus请求的参数：起始地址和结束地址
        int[][] addressRangesHoldingRegisters = {
                {4096, 4103},
                {4156, 4156},
                {4160, 4160},
                {4165, 4165},
                {4180, 4180},
                {4184, 4185},
                {4186, 4187},
                {4188, 4189},
                {4601, 4601}
//                {10000, 10007},
//                {10008, 10008},
//                {10012, 10012},
//                {10017, 10017},
//                {10054, 10054},
//                {10057, 10057},
//                {10058, 10058},
//                {10059, 10059},
//                {10074, 10074}
        };
        int[][] addressRangesCoils = {
                {2079, 2079}
//                {10042, 10042}
        };
        int[][] addressRangesDiscreteInputs = {
                {1290, 1290},
//                {10026, 10026},
        };

        byte readCoilsCode = ModbusConstants.READ_COILS;
        byte readDiscreteInputsCode = ModbusConstants.READ_DISCRETE_INPUTS;
        byte readHoldingRegistersCode = ModbusConstants.READ_HOLDING_REGISTERS;
//        byte writeSingleRegister = ModbusConstants.WRITE_SINGLE_REGISTER;
        int status=1;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesHoldingRegisters, readHoldingRegistersCode,status));
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesCoils, readCoilsCode,status));
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesDiscreteInputs, readDiscreteInputsCode,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean getRunStatusSwitch(String deviceIp) {
        int[][] addressRangesHoldingRegisters = {
                {4157, 4157},
                {4162, 4162},
                {4163, 4163},
//                {10009, 10009},
//                {10014, 10014},
//                {10015, 10015},
        };
        int[][] addressRangesDiscreteInputs = {
                {1026, 1026},
                {1028, 1031},
                {1033, 1033},
                {1035, 1037},
                {1039, 1039},
                {1281, 1281},
                {1284, 1286},
                {1288, 1289},
//                {1290, 1290},
                {1292, 1293},
                {1296, 1297},
        };
        int[][] addressRangesCoils = {
                {2124, 2124}
        };

        byte readHoldingRegistersCode = ModbusConstants.READ_HOLDING_REGISTERS;
        byte readDiscreteInputsCode = ModbusConstants.READ_DISCRETE_INPUTS;
        byte readCoilsCode = ModbusConstants.READ_COILS;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        int status=1;
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesHoldingRegisters, readHoldingRegistersCode,status));
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesCoils, readCoilsCode,status));
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesDiscreteInputs, readDiscreteInputsCode,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean getSingleVoltageList(String deviceIp) {
        int[][] addressRangesHoldingRegisters = {
                {10226, 10249},
//                {10370, 10417},
        };
        byte readHoldingRegistersCode = ModbusConstants.READ_HOLDING_REGISTERS;
        int status=1;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressRangesHoldingRegisters, readHoldingRegistersCode,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean getRunStatusAlarm(String deviceId) {

        int[][] addressRangesCoils = {
                {2069, 2071},
                {2078, 2119},
                {2123, 2124},
//                {10038, 10040},
//               {10041, 10050},

        };
        byte readCoilsCode = ModbusConstants.READ_COILS;
        int status=1;

        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceId, addressRangesCoils, readCoilsCode,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
     }

    @Override
    public boolean onDevice(String deviceIp, int addressWriteSingleRegister[][]) {
        byte writeSingleRegister = ModbusConstants.WRITE_SINGLE_COIL;
        int status=1;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressWriteSingleRegister, writeSingleRegister,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean offDevice(String deviceIp, int addressWriteSingleRegister[][]) {
        byte writeSingleRegister = ModbusConstants.WRITE_SINGLE_COIL;
        int status=0;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, addressWriteSingleRegister, writeSingleRegister,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }
    @Override
    public boolean test(String deviceIp, int[][] address) {
        byte readHoldingRegisters = ModbusConstants.READ_HOLDING_REGISTERS;
        int status=0;
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, address, readHoldingRegisters,status));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean inputHoldingRegister(ModbusRequest modbusRequest) {

        byte readHoldingRegisters = ModbusConstants.WRITE_SINGLE_REGISTER;
        String deviceIp = modbusRequest.getDeviceIp();
        int[][] address = modbusRequest.getAddress();
        Integer value = modbusRequest.getValue();

        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, address, readHoldingRegisters,value));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    @Override
    public boolean getTest(ModbusRequest modbusRequest) {
        byte readHoldingRegisters = ModbusConstants.READ_HOLDING_REGISTERS;
        String deviceIp = modbusRequest.getDeviceIp();
        int[][] address = modbusRequest.getAddress();
        Integer value = modbusRequest.getValue();

        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        futures.addAll(confirmModbusRequestAddress(deviceIp, address, readHoldingRegisters,value));
        // 等待所有的Future完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        try {
            // 检查所有future是否都成功完成
            for (CompletableFuture<Boolean> future : futures) {
                if (!future.get()) { // .get() 会抛出异常，如果future因异常而完成
                    return false; // 如果有任何一个future不是正常完成，返回false
                }
            }
            return true; // 只有当所有future都正常完成时，才返回true
        } catch (InterruptedException | ExecutionException e) { // 处理get可能抛出的异常
            return false;
        }
    }

    /**
     * 动态构建modbus请求方法
     *
     * @param startAddress 读取的起始地址
     * @param size         需要读取的个数
     * @param functionCode 功能码
     */
    public ModbusFrame createModbusRequest(int startAddress, int size, byte functionCode,int status) {
        // 使用transactionId，并立即增加1，为下一次请求做准备
        // 注意处理溢出，确保transactionId始终在0到65535之间
        int transactionId = currentTransactionId;
        currentTransactionId = (currentTransactionId + 1) % 65536;
        int protocolId = 0;
        int unitId = 1;
        int length = 6; // Modbus请求的长度，此处以功能码03查询为例
        if (functionCode==ModbusConstants.WRITE_SINGLE_COIL){
//            modbusAndResultMap.put(startAddress, Optional.empty());
            log.info("写操作");

            ByteBuf buf = Unpooled.buffer();
            byte[] bytesByStarAddress = ByteUtils.shortToByte2((short) startAddress);
            int quantityOfRegisters=0;
            if (status==1){
                quantityOfRegisters = 0xFF00;
            }else {
                quantityOfRegisters = 0x0000;
            }
            buf.writeBytes(bytesByStarAddress);
            buf.writeShort(quantityOfRegisters);
            ModbusFrame modbusFrame = new ModbusFrame(transactionId, protocolId, length, unitId, functionCode,buf);
            integerModbusFrameMap.put(modbusFrame.getTransactionId(), modbusFrame);
            return modbusFrame;
        }
        if (functionCode==ModbusConstants.WRITE_SINGLE_REGISTER){
            ByteBuf buf = Unpooled.buffer();
            byte[] bytesByStarAddress = ByteUtils.shortToByte2((short) startAddress);
            buf.writeBytes(bytesByStarAddress);
            buf.writeShort(status);
            ModbusFrame modbusFrame = new ModbusFrame(transactionId, protocolId, length, unitId, functionCode,buf);
            integerModbusFrameMap.put(modbusFrame.getTransactionId(), modbusFrame);
            return modbusFrame;
        }
        for (int i = startAddress; i < startAddress + size; i++) {
            modbusAndResultMap.put(i, Optional.empty());
        }
        //读取的起始地址
        byte[] bytesByStarAddress = ByteUtils.shortToByte2((short) startAddress);
        //读取的长度
        byte[] bytesBySize = ByteUtils.shortToByte2((short) size);
        ByteBuf buf = Unpooled.buffer();
        buf.writeBytes(bytesByStarAddress);
        buf.writeBytes(bytesBySize);

        ModbusFrame modbusFrame = new ModbusFrame(transactionId, protocolId, length, unitId, functionCode, buf);
        integerModbusFrameMap.put(modbusFrame.getTransactionId(), modbusFrame);
        return modbusFrame;
    }

    public void getDeviceStatusList(String deviceIp) {
        // 定义Modbus请求的参数：起始地址和结束地址
        int[][] addressRangesHoldingRegisters = {
                {4096, 4103},
                {4116, 4117},
                {4156, 4168},
                {4176, 4188},
                {4596, 4615},
                {4697, 4706},
                {4796, 4797},
                {4802, 4829},
                {4839, 4839}
        };
        int[][] addressRangesCoils = {
                {2048, 2049},
                {2058, 2137},
                {2148, 2149},
                {2173, 2173},
                {2178, 2178},
                {2179, 2179},
                {2203, 2203},
                {2714, 2714},
        };
        int[][] addressRangesDiscreteInputs = {
                {1024, 1039},
                {1280, 1297},
                {10226, 10248}
        };
        byte readHoldingRegistersCode = ModbusConstants.READ_HOLDING_REGISTERS;
        byte readCoilsCode = ModbusConstants.READ_COILS;
        byte readDiscreteInputsCode = ModbusConstants.READ_DISCRETE_INPUTS;
        int status=1;
        confirmModbusRequestAddress(deviceIp, addressRangesHoldingRegisters, readHoldingRegistersCode,status);
        confirmModbusRequestAddress(deviceIp, addressRangesCoils, readCoilsCode,status);
        confirmModbusRequestAddress(deviceIp, addressRangesDiscreteInputs, readDiscreteInputsCode,status);

    }

    /**
     *  发送请求到netty服务端
     * @param deviceIp 设备ip
     * @param usuallyAddress 读取的地址
     * @param readHoldingRegistersCode 功能码
     * @return
     */
    private List<CompletableFuture<Boolean>> confirmModbusRequestAddress(String deviceIp, int[][] usuallyAddress, byte readHoldingRegistersCode,int status) {
        List<CompletableFuture<Boolean>> futures = new ArrayList<>();
        for (int[] range : usuallyAddress) {
            int startAddress = range[0];
            int quantityOfRegisters = (range[1] - range[0]) + 1;  // 计算需要读取的寄存器数量
            // 调用createModbus方法创建Modbus请求
            ModbusFrame modbusRequest = createModbusRequest(startAddress, quantityOfRegisters, readHoldingRegistersCode,status);
            CompletableFuture<Boolean> future = new CompletableFuture<>();
            pendingRequests.put(modbusRequest.getTransactionId(),future);
            Channel channel = ChannelMap.getChannel(deviceIp);
            channel.writeAndFlush(modbusRequest);
            futures.add(future);
        }
        return futures;
    }

}